\subsubsection{C++内存详解}
\begin{enumerate}
    \item 栈区： 由编译器自动分配释放，像局部变量，函数参数，都是在栈区。会随着作用域退出而释放空间。
    \item 堆区：程序员分配并释放的区域，像malloc(c),new(c++)
    \item 全局数据区(静态区)：全局变量和静态便令的存储是放在一块的，初始化的全局变量和静态变量在一块区域，未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束释放。
    \item 代码区
\end{enumerate}
在内存中存储位置如\figref{fig:cpp_memory}
\begin{figure}[H]
    \centering
    \includegraphics[width=\textwidth]{cpp_memory}
    \caption{C++内存存储区域图}
    \label{fig:cpp_memory}
\end{figure}
static变量随着第一次函数调用而初始化，却不随着函数的调用结束而销毁。相比全局变量，static变量属于函数本身而全局变量不属于函数本身。静态局部变量在全局数据区而不是保存在栈中，每次值保存到下次调用，直到下次赋值新值。
\cppfile{code/memory/local_static.cxx}
输出结果如下：
\begin{bash}
    全局数据区值:3
    3
    栈空间下变量：3
    3
    全局数据区值:4
    5
    栈空间下变量：3
    4
    全局数据区值:5
    7
    栈空间下变量：3
    5
    全局数据区值:6
    9
    栈空间下变量：3
    6
\end{bash}
函数局部static变量local，在每次赋值后依然保存，每次返回的时候+1,下次调用的时候值依旧存在所以值在函数反复调用
的过程中依然存在。栈中变量会随着每次函数结束而销毁，这样每次local会被重新初始化为3,一直保持不变。
静态局部变量的特点：
\begin{enumerate}
    \item 该变量在全局数据区分配内存（局部变量在栈区分配内存）
    \item 静态局部变量在程序执行到该对象的声明处被首次初始化，即以后的函数调用不再进行初始化（局部变量每次函数调用都会被初始化）。
    \item 静态局部变量一般在声明处初始化，如果没有显式初始化，即以后的函数调用不再进行初始化（局部变量每次函数调用都被初始化）。
    \item 它始终驻留在全局数据区，指导程序运行结束。但是其作用域为局部作用域，也就是不能在函数提外使用它（局部变量在栈区，函数结束后立即释放内存）。
\end{enumerate}

静态全局变量：定义在函数体外，用于修饰全局变量表示该变量只在文本文件可见。作用域为该文件内部，生存期：整个程序运行期间。
全局变量访问：
\cppfile{code/memory/global_val_visit.cxx}

静态函数：准确的说，静态函数跟静态全局变量的作用类似，即静态函数不能被其它文件所用。其它文件中的可以定义相同的名字的函数，不会发生冲突。
作用域为改文件内部，生存期：整个程序运行期间。

静态函数的好处和静态全局变量的好处类似：
\begin{enumerate}
    \item 静态函数不能被其它文件所用。
    \item 其他文件中可以定义相同名字的函数不会发生冲突。
\end{enumerate}
在C++类中static有两个主要用法：
\begin{enumerate}
    \item 静态数据成员：用于修饰class数据成员，即静态成员。这种数据成员的生存期大于class对象（实例）。静态数据成员
          是每个class有一份，普通成员是每个实例有一份，因此静态数据成员也叫类变量而普通数据成员也叫做实例变量。
    \item 静态成员函数：用于修饰class的成员函数。静态函数数据类，不属于某一个具体对象。访问方式可以通过对象调用也可以用类名::函数名访问。

\end{enumerate}
\cppfile{code/memory/Rectangle.cxx}
输出结果如下：
\begin{bash}
    Rectangle 类的大小：12
    m_sSum = 12
    m_sSum = 12
    Rectangle 实例的大小：12
    m_sSum = 54
    m_sSum = 66
    sizeof(rect2) = 12
    m_sSum = 66
\end{bash}
sizeof(Rectangle)=12,其大小分别是sizeof(m\_width)、sizeof(m\_height)、sizeof(m\_area)。静态变量ms\_area并不占
Rectangle的内存空间。在调用 StaticGetSum 初始化static变量ms\_area后变量存留在类中，下次创建新的对象的时候
此变量依旧存在，下次调用 StaticGetSum 的时候结果就成了$12+6\times 9=66$。

对于非静态数据成员，每个类对象（实例）都有自己的拷贝。二静态数据成员被当作是类的成员，由该类型的所有对象共享访问，对改类
的多个对象来说，静态数据成员只分配一次内存。静态数据成员存储在全局数据区。静态数据成员定义时要分配空间，所以不能在类声明中对应。
也就是说，每次创建一个Rectangle对象并不会为ms\_area静态成员变量构建一份内容拷贝，它不管创建了多少个Rectangle实例，因为它只与
Rectangle挂钩，和每一个实例没关系。

静态成员函数的特点：
\begin{enumerate}
    \item 静态成员之间可以相互访问，包括静态成员函数访问静态数据成员和访问静态成员函数。
    \item 非静态成员函数可以任意的访问静态成员函数和静态数据成员。
    \item 静态成员函数不能访问非静态成员函数和非静态成员数据。
    \item 调用静态成员函数可以用成员函数访问操作符\bashinline{.}或者是\bashinline{->}为一个类的对象
          或指向类对象的指针调用静态成员函数，可以用\bashinline{类名::函数名}调用（因为它本身属于类）。
\end{enumerate}

\subsubsection{访问控制}
在C++中，类的成员默认为private访问权限。对象是类的实例化，成员函数对于整个类而言确实被所有的实例化对象共享
的，即一个类只保留一份成员函数。每个实例对象都只是对其中的数据成员数初始化，内存映像中每个对象仅仅保留属于
自己的那份数据成员副本。

类定义的成员访问权限：
\begin{itemize}
    \item private：私有控制符。这类成员只能被本类中的成员函数和类的友元函数访问。
    \item protected： 受保护控制符。这类成员可以被本类中的成员函数和类的友元函数访问，也可以被派生类的成员函数和派生类的友元函数访问。
    \item public： 共有控制符。这类成员可以被本类中的成员函数和类的友元函数访问，也可以被类作用域内的其他函数引用。
\end{itemize}
类继承：
\begin{itemize}
    \item 使用private继承：父类的所有成员在子类中变成private。
    \item 使用protected继承：父类的protected一下的成员在子类中编程private，private成员不变。
    \item 使用public继承：父类中的方法属性不发生改变。
\end{itemize}

编译时多态和运行时多态。

编译时多态就是在编译时确定的一种多态性。这个在C++中主要体现在函数模板。
\cppfile{code/memory/compile_polymorphic.cxx}
上面的例子我们可以看到，我们定义了函数模板add用来求和两个数。这两个数据的类型在使用是才知道。main函数中使用个
两个int和double值求和，这里就体现了多态行，即在编译期间，编译器匹配函数模板参数类型，体现了编译期多态。
\cppfile{code/memory/Person.cxx}
抽象类定义了纯虚函数Person，具体类Student和Work需要重写其work方法，因为不同的子类对work处理不同，通过指向
父类的指针调用子类的方法实现同样的方法不同的动作（多态）。

\section{<memory>}
智能指针使得自动、异常安全的对象生存期管理可行。定义于头文件 <memory>，指针类别：
\begin{itemize}
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/unique_ptr.html}{unique\_ptr} (C++11)：拥有独有对象所有权语义的智能指针(类模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/shared_ptr.html}{shared\_ptr(C++11)}：拥有共享对象所有权语义的智能指针(类模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/weak_ptr.html}{weak\_ptr}(C++11):到 std::shared\_ptr 所管理对象的弱引用(类模板)
\end{itemize}
辅助类：
\begin{itemize}
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/owner_less.html}{owner\_less} (C++11)提供基于所有者的，共享指针和弱指针的混合类型的排序(类模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/enable_shared_from_this.html}{enable\_shared\_from\_this}(C++11)：允许对象创建指代自身的 shared\_ptr(类模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/bad_weak_ptr.html}{bad\_weak\_ptr(C++11)}访问指向已销毁对象的 weak\_ptr 时抛出的异常(类)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/default_delete.html}{default\_delete(C++11)}：unique\_ptr 的默认删除器(类模板)
\end{itemize}
\subsection*{分配器}
分配器是封装内存分配策略的类模板。这允许泛型容器从数据自身将内存管理解耦合。定义于头文件 <memory>
\begin{itemize}
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/allocator.html}{allocator}默认的分配器(类模板)
定义于头文件 <memory>
        \begin{cpp}
template< class T >
struct allocator;//(1)
template<>
struct allocator<void>;// (2)    (C++17 中弃用)(C++20 中移除)
\end{cpp}
std::allocator 类模板是所有标准库容器所用的默认分配器 (Allocator) ，若不提供用户指定的分配器。默认分配器无状态，即任何给定的 allocator 实例可交换、比较相等，且能解分配同一 allocator 类型的任何其他实例所分配的内存。
        \begin{itemize}
\item 对 void 的显式特化缺少成员 typedef reference 、 const\_reference 、 size\_type 和 difference\_type 。此特化不声明成员函数。(C++20 前)
\item 所有自定义分配器必须也无状态。    (C++11 前)
\item 自定义分配器可以含有状态。每个容器或其他具分配器对象存储一个提供的分配器实例，并通过 std::allocator\_traits 控制分配器替换。    (C++11 起)
\item 默认分配器满足分配器完整性要求。    (C++17 起)
\end{itemize}
成员类型
        \begin{table}[!htbp]
            \centering
            \caption{Allocator 成员类型}
            \begin{tabular}{m{.5\textwidth}m{.5\textwidth}}
                \toprule
                类型    &定义\\
                \midrule 
                value\_type    &T\\
                pointer (C++17 中弃用)(C++20 中移除)    &T*\\
                const\_pointer (C++17 中弃用)(C++20 中移除)    &const T*\\
                reference (C++17 中弃用)(C++20 中移除)    &T\&\\
                const\_reference (C++17 中弃用)(C++20 中移除)    &const T\&\\
                size\_type    &std::size\_t\\
                difference\_type&std::ptrdiff\_t\\
                propagate\_on \_container\_move \_assignment(C++14)&    std::true\_type\\
                rebind (C++17 中弃用)(C++20 中移除)&    template< class U > struct rebind { typedef allocator<U> other; };\\
                is\_always\_equal(C++17)&    std::true\_type\\
\bottomrule
                \end{tabular}
        \end{table}
成员函数
        \begin{itemize}
\item (构造函数)：创建新的 allocator 实例(公开成员函数)
\item (析构函数)：析构 allocator 实例(公开成员函数)
\item address：(C++17 中弃用)(C++20 中移除)
\item 获得对象的地址，即使重载了 operator\&(公开成员函数)
\item \href{https://www.apiref.com/cpp-zh/cpp/memory/allocator/allocate.html}{allocate}：分配未初始化的存储(公开成员函数)
\item \href{https://www.apiref.com/cpp-zh/cpp/memory/allocator/deallocate.html}{deallocate}：解分配存储(公开成员函数)
\item max\_size:(C++17 中弃用)(C++20 中移除)返回最大的受支持分配大小(公开成员函数)
\item construct(C++17 中弃用)(C++20 中移除)：在分配的存储构造对象(公开成员函数)
\item destroy(C++17 中弃用)(C++20 中移除)：析构在已分配存储中的对象(公开成员函数)
        \end{itemize}
非成员函数
        \begin{itemize}
\item operator==、operator!= (C++20 中移除)：比较两个分配器实例(公开成员函数)
        \end{itemize}
        \begin{remark}
成员模板 rebind 提供获得不同类型的 allocator 的方式。例如，
            \begin{itemize}
\item std::list<T, A> 用分配器 A::rebind<Node<T>>::other 分配某个内部类型 Node<T> 结点    (C++11 前)
\item std::list<T, A> 用分配器 std::allocator\_traits<A>::rebind\_alloc<Node<T>> 分配某个内部类型 Node<T> 结点，这用 A::rebind<Node<T>>::other 实现，若 A 是 std::allocator    (C++11 起)
            \end{itemize}
        \end{remark}

    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/allocator_traits.html}{allocator\_traits}(C++11)提供关于分配器类型的信息(类模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/allocator_arg_t.html}{allocator\_arg\_t}(C++11)标签类型，用于选择具分配器的构造函数重载(类)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/allocator_arg.html}{allocator\_arg}(C++11)用于选择具分配器的构造函数的 std::allocator\_arg\_t 对象(常量)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/uses_allocator.html}{uses\_allocator}(C++11)检查指定的类型是否支持使用分配器的构造(类模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/uses_allocator_construction_args.html}{uses\_allocator\_construction\_args}(C++20)准备匹配给定类型所要求的使用分配器构造的口味的参数列表(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/make_obj_using_allocator.html}{make\_obj\_using\_allocator}(C++20)以使用分配器构造的手段创建给类型的对象(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/scoped_allocator_adaptor.html}{uninitialized\_construct\_using\_allocator}(C++20)以使用分配器构造的手段在指定的内存位置创建给定类型的对象(函数模板)定义于头文件 <scoped\_allocator> scoped\_allocator\_adaptor (C++11) 为多级容器实现的多级分配器(类模板)    定义于头文件 <memory\_resource>定义于命名空间 std::pmr
\item \href{https://www.apiref.com/cpp-zh/cpp/memory/polymorphic_allocator.html}{polymorphic\_allocator}(C++17)以 std::memory\_resource 构造，支持基于它的运行时多态的分配器(类模板)
\end{itemize}
\subsection*{内存资源}
内存资源实现可为 \href{https://www.apiref.com/cpp-zh/cpp/memory/polymorphic\_allocator.html}{std::pmr::polymorphic\_allocator} 所用的内存分配策略。定义于头文件 <memory\_resource> ，定义于命名空间 std::pmr。
\begin{itemize}
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/memory_resource.html}{memory\_resource}(C++17)一个抽象接口，用于各种封装内存资源的类(类)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/new_delete_resource.html}{new\_delete\_resource}(C++17)返回一个静态的程序范围 std::pmr::memory\_resource，它使用全局 operator new 与 operator delete 分配和解分配内存(函数)
\item \href{https://www.apiref.com/cpp-zh/cpp/memory/null_memory_resource.html}{null\_memory\_resource}(C++17)返回一个不进行任何分配的静态 std::pmr::memory\_resource(函数)
\item \href{https://www.apiref.com/cpp-zh/cpp/memory/get_default_resource.html}{get\_default\_resource}(C++17)获取缺省 std::pmr::memory\_resource(函数)
\item \href{https://www.apiref.com/cpp-zh/cpp/memory/set_default_resource.html}{set\_default\_resource}(C++17)设置缺省 std::pmr::memory\_resource(函数)
\item \href{https://www.apiref.com/cpp-zh/cpp/memory/pool_options.html}{pool\_options}(C++17)一组池资源的构造函数选项(类)
\item \href{https://www.apiref.com/cpp-zh/cpp/memory/synchronized_pool_resource.html}{synchronized\_pool\_resource}(C++17)线程安全的 std::pmr::memory\_resource，用于管理具有不同块大小的池中的分配(类)
\item \href{https://www.apiref.com/cpp-zh/cpp/memory/unsynchronized_pool_resource.html}{unsynchronized\_pool\_resource}(C++17)线程不安全的 std::pmr::memory\_resource，用于管理具有不同块大小的池中的分配(类)
\item \href{https://www.apiref.com/cpp-zh/cpp/memory/monotonic_buffer_resource.html}{monotonic\_buffer\_resource}(C++17)一种特殊用途的 std::pmr::memory\_resource，仅在资源被销毁时才释放所分配内存(类)
\end{itemize}
\subsection*{未初始化内存算法}
定义于头文件 <memory>
\begin{itemize}
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/uninitialized_copy.html}{uninitialized\_copy}：将范围内的对象复制到未初始化的内存区域(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/uninitialized_copy_n.html}{uninitialized\_copy\_n}(C++11)：将指定数量的对象复制到未初始化的内存区域(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/uninitialized_fill.html}{uninitialized\_fill}：复制一个对象到以范围定义的未初始化内存区域(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/uninitialized_fill_n.html}{uninitialized\_fill\_n}：复制一个对象到以起点和计数定义的未初始化内存区域(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/uninitialized_move.html}{uninitialized\_move}：(C++17)移动一个范围的对象到未初始化的内存区域(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/uninitialized_move_n.html}{uninitialized\_move\_n}(C++17)移动一定数量对象到未初始化内存区域(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/uninitialized_default_construct.html}{uninitialized\_default\_construct}(C++17)在范围所定义的未初始化的内存区域以默认初始化构造对象(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/uninitialized_default_construct_n.html}{uninitialized\_default\_construct\_n}(C++17)在起始和计数所定义的未初始化内存区域用默认初始化构造对象(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/uninitialized_value_construct.html}{uninitialized\_value\_construct}(C++17)在范围所定义的未初始化内存中用值初始化构造对象(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/uninitialized_default_construct_n.html}{uninitialized\_value\_construct\_n}(C++17)在起始和计数所定义的未初始化内存区域以值初始化构造对象(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/destroy_at.html}{destroy\_at}(C++17)销毁在给定地址的对象(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/destroy.html}{destroy}(C++17)销毁一个范围中的对象(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/destroy_n.html}{destroy\_n}(C++17)销毁范围中一定数量的对象(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/construct_at.html}{construct\_at}(C++20)在给定地址创建对象(函数模板)
\end{itemize}
\subsection*{有制约的未初始化内存算法 (C++20)}
C++20 提供有制约的未初始化内存算法，它们接受范围参数或迭代器-哨位对。定义于头文件 <memory>定义于命名空间 std::ranges。
\begin{itemize}
    \item \href{}{ranges::uninitialized\_copy}(C++20)复制元素范围到未初始化的内存区域(niebloid)
    \item \href{}{ranges::uninitialized\_copy\_n}(C++20)复制一定量元素到未初始化的内存区域(niebloid)
    \item \href{}{ranges::uninitialized\_fill}(C++20)复制一个对象到范围所定义的未初始化的内存区域(niebloid)
    \item \href{}{ranges::uninitialized\_fill\_n}(C++20)复制一个对象到起始与计数所定义的未初始化的内存区域(niebloid)
    \item \href{}{ranges::uninitialized\_move}(C++20)移动对象范围到未初始化的内存区域(niebloid)
    \item \href{}{ranges::uninitialized\_move\_n}(C++20)移动一定量对象到未初始化的内存区域(niebloid)
    \item \href{}{ranges::uninitialized\_default\_construct}(C++20)在范围所定义的未初始化的内存区域以默认初始化构造对象(niebloid)
    \item \href{}{ranges::uninitialized\_default\_construct\_n}(C++20)在起始与计数所定义的未初始化的内存区域以默认初始化构造对象(niebloid)
    \item \href{}{ranges::uninitialized\_value\_construct}(C++20)在范围所定义的未初始化的内存区域以值初始化构造对象(niebloid)
    \item \href{}{ranges::uninitialized\_value\_construct\_n}(C++20)在起始与计数所定义的未初始化的内存区域以值初始化构造对象(niebloid)
    \item \href{}{ranges::destroy\_at}(C++20)销毁位于给定地址的元素(niebloid)
    \item \href{}{ranges::destroy}(C++20)销毁范围中的元素(niebloid)
    \item \href{}{ranges::destroy\_n}(C++20)销毁范围中一定量的元素(niebloid)
    \item \href{}{ranges::construct\_at}(C++20)在给定地址创建对象(niebloid)
\end{itemize}
\subsection*{垃圾收集器支持}
定义于头文件 <memory>
\begin{itemize}
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/gc/declare_reachable.html}{declare\_reachable}(C++11)声明一个对象不能被回收(函数)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/gc/undeclare_reachable.html}{undeclare\_reachable}(C++11)声明一个对象可以被回收(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/gc/declare_no_pointers.html}{declare\_no\_pointers}(C++11)声明该内存区域不含可追踪指针(函数)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/gc/undeclare_no_pointers.html}{undeclare\_no\_pointers}(C++11)取消 std::declare\_no\_pointers 的效果(函数)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/gc/pointer_safety.html}{pointer\_safety}(C++11)列出指针安全模式(枚举)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/gc/get_pointer_safety.html}{get\_pointer\_safety}(C++11)返回当前的指针安全模式(函数)
\end{itemize}
\subsection*{杂项}
定义于头文件 <memory>
\begin{itemize}
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/pointer_traits.html}{pointer\_traits}(C++11)提供关于指针式类型的信息(类模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/to_address.html}{to\_address}(C++20)从指针式类型获得裸指针(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/addressof.html}{addressof}(C++11)获得对象的实际地址，即使其重载了 \& 运算符(函数模板)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/align.html}{align}(C++11)对齐缓冲区中的指针(函数)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/assume_aligned.html}{assume\_aligned}(C++20)
\end{itemize}
告知编译器指针已对齐(函数模板)
\subsection{unique\_ptr}
 C++ 工具库 动态内存管理 std::unique\_ptr，定义于头文件 <memory>。
\begin{cpp}
template<
    class T,
    class Deleter = std::default_delete<T>
> class unique_ptr;//(1)    (C++11 起)
template <
    class T,
    class Deleter
> class unique_ptr<T[], Deleter>;//(2)    (C++11 起)
\end{cpp}
std::unique\_ptr 是通过指针占有并管理另一对象，并在 unique\_ptr 离开作用域时释放该对象的智能指针。在下列两者之一发生时用关联的删除器释放对象：
\begin{itemize}
\item 销毁了管理的 unique\_ptr 对象
\item 通过 operator= 或 reset() 赋值另一指针给管理的 unique\_ptr 对象。
\end{itemize}
通过调用 get\_deleter()(ptr) ，用潜在为用户提供的删除器释放对象。默认删除器用 delete 运算符，它销毁对象并解分配内存。unique\_ptr 亦可以不占有对象，该情况下称它为空 (empty)。std::unique\_ptr 有两个版本：
\begin{enumerate}
\item 管理单个对象（例如以 new 分配）
\item 管理动态分配的对象数组（例如以 new[] 分配）
\end{enumerate}
类满足可移动构造 (MoveConstructible) 和可移动赋值 (MoveAssignable) 的要求，但不满足可复制构造 (CopyConstructible) 或可复制赋值 (CopyAssignable) 的要求。

类型要求：Deleter 必须是函数对象 (FunctionObject) 或到函数对象 (FunctionObject) 的左值引用或到函数的左值引用，可以 unique\_ptr<T, Deleter>::pointer 类型参数调用
\begin{Notice}{}{}
只有非 const 的 unique\_ptr 能转移被管理对象的所有权给另一 unique\_ptr 。若对象的生存期为 const std::unique\_ptr 所管理，则它被限定在创建指针的作用域中。

std::unique\_ptr 常用于管理对象的生存期，包含：
\begin{itemize}
\item 通过正常退出和经由异常退出两者上的受保证删除，提供异常安全，给处理拥有动态生存期的对象的类和函数
\item 传递独占的拥有动态生存期的对象的所有权到函数
\item 从函数获得独占的拥有动态生存期对象的所有权
\item 作为具移动容器的元素类型，例如保有指向动态分配对象的指针的 std::vector （例如，若想要多态行为）
\end{itemize}
std::unique\_ptr 可为不完整类型 T 构造，例如用于改善用作 pImpl 手法中柄的用途。若使用默认删除器，则 T 必须在代码中调用删除器点处完整，这发生于析构函数、移动赋值运算符和 std::unique\_ptr 的 reset 成员函数中。（相反地， std::shared\_ptr 不能从指向不完整类型的裸指针构造，但可于 T 不完整处销毁）。注意若 T 是类模板特化，则以 unique\_ptr 为运算数的使用，如 !p ，因 ADL 而要求 T 的形参完整。


若 T 是某基类 B 的导出类，则 std::unique\_ptr<T> 可隐式转换为 std::unique\_ptr<B>。产生的 std::unique\_ptr<B> 的默认删除器将使用 B 的 operator delete ，这导致未定义行为，除非 B 的析构函数为虚。注意 std::shared\_ptr 表现有别： std::shared\_ptr<B> 将使用类型 T 的 operator delete ，而且即使 B 的析构函数非虚，也会正确删除被占有对象。

不同于 std::shared\_ptr ， std::unique\_ptr 可通过任何满足可空指针 (NullablePointer) 的定制柄类型管理对象。例如，这允许管理位于共享内存，但提供定义 typedef boost::offset\_ptr pointer; 或其他缀饰指针的 Deleter 的对象。
\end{Notice}
\textbf{成员类型}
\begin{itemize}
\item pointer：若该类型存在则为 std::remove\_reference<Deleter>::type::pointer ，否则为 T* 。必须满足可空指针 (NullablePointer) 。
\item element\_type    T ，此 unique\_ptr 所管理的对象类型
\item deleter\_type    Deleter：函数对象或到函数或到函数对象的左值引用，会从析构函数调用。
\end{itemize}
\textbf{成员函数}
\begin{itemize}
\item (构造函数)：构造新的unique\_ptr(公开成员函数)
\item (析构函数)：析构所管理的对象，如果存在的话(公开成员函数)
\item operator=：为unique\_ptr赋值(公开成员函数)
\end{itemize}
\textbf{修改器:}
\begin{itemize}
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/unique_ptr/release.html}{release}：返回一个指向被管理对象的指针，并释放所有权(公开成员函数)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/unique_ptr/reset.html}{reset}：替换被管理对象(公开成员函数)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/unique_ptr/swap.html}{swap}：交换被管理对象(公开成员函数)
\end{itemize}
\textbf{观察器}：
\begin{itemize}
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/unique_ptr/get.html}{get}：返回指向被管理对象的指针(公开成员函数)。
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/unique_ptr/get_deleter.html}{get\_deleter}：返回用于析构被管理对象的删除器(公开成员函数)
    \item \href{https://www.apiref.com/cpp-zh/cpp/memory/unique_ptr/operator_bool}{operator bool}：检查是否有关联的被管理对象(公开成员函数)
\item 单对象版本， unique\_ptr<T>,operator*、operator->：解引用指向被管理对象的指针(公开成员函数)
\item 数组版本， unique\_ptr<T[]>,operator[]：提供到被管理数组的有索引访问(公开成员函数)。
\end{itemize}
\textbf{非成员函数}
\begin{itemize}
        \item make\_unique(C++14)，make\_unique\_for\_overwrite(C++20)：创建管理一个新对象的独占指针。
        \item operator==、operator!=、operator<、operator<=、operator>、operator>=(C++20 中移除)、operator<=>(C++20)与另一个 unique\_ptr 或 nullptr 进行比较。

\item operator<<(C++20)：输出被管理指针的值到输出流(函数模板)
\item std::swap(std::unique\_ptr)(C++11)：特化 std::swap 算法(函数模板)
\end{itemize}
\textbf{辅助类}
\begin{itemize}
\item std::hash<std::unique\_ptr>(C++11)：std::unique\_ptr 的散列支持(类模板特化)
\end{itemize}
\begin{longlisting}
\cppfile{sample/memory/unique_ptr_demo.cc}
    \caption{unique\_ptr示例}
    \label{code:unique_ptr}
\end{longlisting}
输出：
\begin{bash}
独占指针使用
D::D
D::bar
D::bar
D::~D
多态使用
D::D
D::bar
D::D
D::D
D::bar
D::bar
D::bar
D::~D
D::~D
D::~D
Custom deleter demo
x
Custom lambda-expression deleter demo
D::D
D::bar
destroying from a custom deleter...
D::~D
Array form of unique_ptr demo
D::D
D::D
D::D
D::~D
D::~D
D::~D
\end{bash}
\subsection{\href{https://zh.cppreference.com/w/cpp/language/static_cast}{static\_cast}}
用于隐式转换数据类型。
\begin{cpp}
    static_cast < 新类型 > (表达式)
\end{cpp}
返回\textbf{新类型}类型的值。只有下列转换在不去除常量性或易变性的场合才能用 static\_cast 执行。
\begin{enumerate}
    \item 如果\textbf{新类型}是到某个类类型 D 的引用并且\textbf{表达式}的类型是它的\textcolor{red}{非虚基类} B 的左值，或者\textbf{新类型}是\textcolor{red}{指向某个完整类类型 D 的指针并且\textbf{表达式}的类型是指向它的非虚基类 B 的指针纯右值}，那么 static\_cast 进行向下转型（downcast）。如果 B 是 D 的有歧义的，不可访问的或虚的基类（或虚基类的基类），那么此向下转型非良构。
这种 static\_cast 不会在运行时检查该对象的运行时类型确实为 D，因此它只能在该前提条件通过其他方法保证时，例如在实现静多态时，才能安全使用。安全的向下转型可以用 dynamic\_cast 执行。如果\textbf{表达式}指代或指向的对象确实是具有 D 类型的对象的基类子对象，那么结果指代的是具有 D 类型的该外围对象。否则行为未定义：
        \begin{cpp}
            struct B {};
            struct D : B { B b };
             
            D d;
            B& br1 = d;
            B& br2 = d.b;
            static_cast<D&>(br1); // OK：该左值指代原来的 d 对象
            static_cast<D&>(br2); // 未定义行为：子对象 b 不是基类子对象
            \end{cpp}
        \item 如果 \textbf{新类型} 是右值引用类型，那么 static\_cast 将泛左值、类纯右值或数组纯右值 (C++17 前)任何左值 (C++17 起)\textbf{表达式}的值转换为与该表达式指代相同对象，或指代其基类子对象（取决于 新类型）的亡值。如果目标类型是表达式的不可访问或有歧义的基类，那么程序非良构。如果表达式是位域左值，那么它会首先被转换成底层类型的纯右值。这种 static\_cast 用于在 std::move 中实现移动语义。(C++11 起)
        \item 如果存在从 \textbf{表达式} 到 \textbf{新类型} 的隐式转换序列，或者如果针对以 \textbf{表达式} 对 \textbf{新类型} 类型的对象或引用所进行的\nameref{direct_initialization}的重载操作能找到至少一个可行函数，那么 static\_cast<新类型>(表达式) 返回如同以\textbf{新类型}Temp(表达式); 所初始化的一个虚构变量 Temp，它可能涉及隐式转换，对\textbf{新类型}的构造函数的调用，或对用户定义转换运算符的调用。对于非引用的 \textbf{新类型}，static\_cast 纯右值表达式的结果对象是其直接初始化的对象。 (C++17 起)
        \item 如果\textbf{新类型}是（可有 cv 限定的）void 类型，那么 static\_cast 在求值\textbf{表达式}后舍弃该值。
        \item 如果存在从 \textbf{新类型} 到 \textbf{表达式} 类型的标准转换序列，且它不包含左值到右值、数组到指针、函数到指针、空指针、空成员指针、函数指针 (C++17 起)或布尔转换，那么 static\_cast 能进行该隐式转换的逆转换。
        \item 如果从 \textbf{表达式} 到 \textbf{新类型} 的转换涉及左值到右值、数组到指针或函数到指针转换，那么 static\_cast 可以显式执行该转换。
        \item 有作用域枚举类型能转换到整数或浮点类型。
当目标类型是（可有 cv 限定的）bool 类型时，如果原值为零那么结果是 false，而对所有其他值结果是 true。对于其余整型类型，如果该枚举的值能以目标类型表示，那么结果是该值，否则结果未指明。(C++20 前)
它的结果与从枚举的底层类型隐式转换成目标类型的结果相同。(C++20 起)(C++11 起)
        \item 整数或枚举类型值可转换到任何完整的枚举类型。
如果底层类型不固定，那么当\textbf{表达式}的值落在范围（范围是大到足以保有目标枚举的所有枚举项的最小位域的所有可能值）外时，行为未定义。
如果底层类型固定，那么它的结果与转换原值到枚举的底层类型再到该枚举类型的结果相同。
 浮点类型的值也可以转换到任何完整枚举类型。
它的结果与转换原值到枚举的底层类型再到该枚举类型的结果相同。
\item 指向某完整类 D 的成员的指针可以向上转型（upcast）到指向它的无歧义、可访问的基类 B 的成员。这种 static\_cast 不检查所指向对象的运行时类型是否包含该成员。
\item 指向（可有 cv 限定的）void 的指针类型的纯右值可以转换到指向任何对象的指针类型。如果原指针值所表示的内存中字节地址不满足目标类型的对齐要求，那么结果指针值未指明。否则，如果原指针值指向对象 a，且存在与 a 指针可以互相转换（在下文定义）的目标类型（忽略 cv 限定）的对象 b，那么结果是指向 b 的指针。否则指针值不改变。任何指针转换到 void 指针再转换回原（或有更多 cv 限定的）类型的指针都保持它的原值。
同所有转型表达式，结果是：
        \begin{itemize}
            \item 左值，如果\textbf{新类型}是左值引用类型或到函数类型的右值引用类型 (C++11 起)；
            \item 亡值，如果\textbf{新类型}是到对象类型的右值引用类型；(C++11 起)
            \item 否则是纯右值。
        \end{itemize}
满足以下条件时，两个对象 a 与 b 的指针可以互相转换（pointer-interconvertible）：
        \begin{itemize}
            \item 它们是同一个对象，或
            \item 一个是联合体对象而另一个是该对象的非静态数据成员，或
            \item 一个是标准布局的类对象，而另一个是该对象的首个非静态数据成员，或是该对象的任何基类子对象，或存在对象 c 使得 a 与 c 的指针可以互相转换，而 c 与 b 的指针可以互相转换。
        \begin{cpp}
union U { int a; double b; } u;
void* x = &u;                        // x 的值是“指向 u 的指针”
double* y = static_cast<double*>(x); // y 的值是“指向 u.b 的指针”
char* z = static_cast<char*>(x);     // z 的值是“指向 u 的指针”
        \end{cpp}
                \begin{remark}
static\_cast 也能用来通过进行到指定类型的函数到指针转换来消解函数重载的歧义，如
                    \begin{cpp}
std::for_each(files.begin(), files.end(),
              static_cast<std::ostream&(*)(std::ostream&)>(std::flush));
                    \end{cpp}
                \end{remark}
            \end{itemize}
        \end{enumerate}
\begin{longlisting}
\cppfile{sample/memory/static_cast_demo.cc}
\caption{static\_cast转换示例}
\label{code:static_cast_basic}
\end{longlisting}

输出：
\begin{bash}
1) Hello world, this is B!
1) Hello world, this is D!
2) 转换之后移动数据, v0.size() = 0 v2.size() = 3
3) 转换为 int 之后 n = 3
3) v.size() = 10
4) n = 3 ni = 3
7) 2
9) 42
\end{bash}
